﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Weazel.Willows.Model
{
	public abstract class HierarchicalEntity 
		: IHierarchicalEntity
	{
		public sealed class HierarchyRoot
			:	HierarchicalEntity
		{
			public HierarchyRoot()
				: base(null)
			{
			}
		}

		private IHierarchicalEntity parent;
		public IHierarchicalEntity Parent
		{
			get { return parent; }
		  set 
			{
				if (value == null)
					throw new NullReferenceException();

				parent = value; 
			}
		}
		
		private string localName;
		public string LocalName
		{
			get 
			{
				if (localName == null)
				  throw new NullReferenceException("LocalName not set");

				return localName; 
			}
			/*protected*/ set 
			{
				if (value == null)
				{
					localName = null;
					return;
				}

				if (value.Contains("."))
				{
					string message =
						string.Format("LocalName '{0}' must not include '.'", value);

					throw new NotSupportedException(message);
				}

				localName = value; 
			}
		}

		private string hierarchicalName;
		public string HierarchicalName
		{
			get { return hierarchicalName; }
			set { hierarchicalName = value; }
		}

		private string createNameFromStack(Stack<string> stack)
		{
			StringBuilder str = new StringBuilder();
			while (stack.Count != 0)
				str.Append(stack.Pop());

			str.Append(LocalName);
			return str.ToString();
		}

		public string Name
		{
			get
			{
				
				Stack<string> stack = new Stack<string>();

				IHierarchicalEntity current = this.Parent;

				while (!(current is HierarchyRoot))
				{
					if (current == null)
						throw new NullReferenceException("Missing element: ?." + createNameFromStack(stack));

					if (current.LocalName == null)
						throw new NullReferenceException(LocalName);

					stack.Push(current.LocalName + ".");
					current = current.Parent;
				};

				return createNameFromStack(stack);
			}
		}	

		public HierarchicalEntity(IHierarchicalEntity parent, string localName)
		{
			this.parent = parent;
			this.LocalName = localName;
		}

		protected HierarchicalEntity(IHierarchicalEntity parent)
		{
			this.parent = parent;
			this.localName = null;
		}

		public override string ToString()
		{
			return LocalName;
		}
	}
}
